import type { Directive, VNode, ComponentInternalInstance } from "vue";

type VNodeType = VNode & { ctx?: ComponentInternalInstance };

const queryInputElement = (vnode: VNodeType) => {
  let inputVnode: VNodeType | undefined;
  if (vnode.type === "input" || vnode.type === "textarea") {
    inputVnode = vnode;
  } else if (Array.isArray(vnode.children)) {
    vnode.children.forEach(_vnode => {
      if (!!queryInputElement(_vnode as VNodeType)) {
        inputVnode = queryInputElement(_vnode as VNodeType);
      }
    });
  }
  return inputVnode;
};

const trim: Directive = {
  mounted: (el, binding, vnode) => {
    const inputNode = queryInputElement(vnode);
    if (!inputNode?.el) return;
    inputNode.el.handle_keydown = (event: Event) => {
      const { key, code } = event as KeyboardEvent;
      const target = event.target as HTMLInputElement;
      const selectionStart = target.selectionStart || 0;
      if (selectionStart === 0 && (key === " " || code === "Space")) {
        event.preventDefault();
      }
      if (key==='Enter' || code ==='Enter') {
        event.preventDefault();
      }
    };
    inputNode.el.handle_input = () => {
      inputNode.ctx?.emit("update:modelValue", inputNode.el?.value.replace(/^\s+/g, ""));
    };
    inputNode.el.handle_blur = () => {
      inputNode.ctx?.emit("update:modelValue", inputNode.el?.value.trim());
    };
    inputNode.el.addEventListener("keydown", inputNode.el.handle_keydown);
    inputNode.el.addEventListener("input", inputNode.el.handle_input);
    inputNode.el.addEventListener("blur", inputNode.el.handle_blur);
  },

  beforeUnmount: (el, binding, vnode) => {
    const inputNode = queryInputElement(vnode);
    if (!inputNode?.el) return;
    inputNode.el.addEventListener("keydown", inputNode.el.handle_keydown);
    inputNode.el.addEventListener("input", inputNode.el.handle_input);
    inputNode.el.addEventListener("blur", inputNode.el.handle_blur);
  }
};

export default trim;
